package com.jinzhi.jzweb.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.jinzhi.common.base.CoreServiceImpl;
import com.jinzhi.common.utils.Result;
import com.jinzhi.jzweb.dao.TrackDrawDao;
import com.jinzhi.jzweb.domain.StuSignUpComDO;
import com.jinzhi.jzweb.domain.TrackDrawDO;
import com.jinzhi.jzweb.service.StuSignUpComService;
import com.jinzhi.jzweb.service.TrackDrawYuLinService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 
 * <pre>
 * 赛道抽签表（存储抽签信息）
 * </pre>
 * <small> 2024-02-28 09:32:18 | lance</small>
 */
@Service
public class TrackDrawYuLinServiceImpl extends CoreServiceImpl<TrackDrawDao, TrackDrawDO> implements TrackDrawYuLinService {

    @Autowired
    private StuSignUpComService stuSignUpComService;


    /**
     * 抽签接口
     *
     * 以参赛校为单位，共64个签号；
     *   赛道号？
     * 上午场：赛道①是1-16号，赛道②是17-32号，共32个号；
     *
     * 下午场：赛道①是33-48号，赛道②是49-64号，共32个号。
     *
     * 参赛院校      参赛选手    赛道号
     *
     * ==============================================
     *
     * 以参赛校为单位，共64个签号；
     * 将17日在赛道①的学校换到赛道②，赛道②的学校换到赛道①；
     *
     * 上午场是17日下午场参赛的学校，重新排号：
     * 赛道①是1-16号，赛道②是17-32号，共32个号；
     *
     * 下午场是17日上午场参赛的学校，重新排号：
     * 赛道①是33-48号，赛道②是49-64号，共32个号。
     * 参赛院校      参赛选手    赛道号
     *
     * @param trackDrawDTO
     * @return
     */

    @Override
    public Result<List<TrackDrawDO>> trackDrawList(TrackDrawDO trackDrawDTO) {
        if(null!=trackDrawDTO.getDrawType()){
            Result.fail("缺少'抽签类型'！");
        }
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);
        if(null==trackDrawDOS || trackDrawDOS.isEmpty()){
            Result.fail("没有选手信息，无法抽签！");
        }
        if (trackDrawDTO.getDrawType()==1) {
            //第一次抽签
            return trackDrawB(trackDrawDOS);
        } else{
            //第二次抽签
            return trackDrawC(trackDrawDOS);
        }
    }

    //第一次抽签
    public Result<List<TrackDrawDO>> trackDrawB(List<TrackDrawDO> trackDrawDOS){
        LinkedList<String> numList = new LinkedList<>();//存储所有数据
        LinkedList<String> num1List = new LinkedList<>();//存储上午场1赛道数据
        LinkedList<String> num2List = new LinkedList<>();//存储上午场2赛道数据
        LinkedList<String> num3List = new LinkedList<>();//存储下午场1赛道数据
        LinkedList<String> num4List = new LinkedList<>();//存储下午场2赛道数据
        LinkedList<String> num1ListOld = new LinkedList<>();
        LinkedList<String> num2ListOld = new LinkedList<>();
        LinkedList<String> num3ListOld = new LinkedList<>();
        LinkedList<String> num4ListOld = new LinkedList<>();
        //这里写死64组学校，不考虑缺赛选手
        for (int i = 1; i <= 64; i++) {
            if(i<=16){
                num1List.add(String.valueOf(i));
                num1ListOld.add(String.valueOf(i));
            } else if (i<=32) {
                num2List.add(String.valueOf(i));
                num2ListOld.add(String.valueOf(i));
            } else if (i<=48) {
                num3List.add(String.valueOf(i));
                num3ListOld.add(String.valueOf(i));
            } else{
                num4List.add(String.valueOf(i));
                num4ListOld.add(String.valueOf(i));
            }
            numList.add(String.valueOf(i));
        }

        Random random = new Random();
        Collections.shuffle(numList, random);  // 随机打乱赛道
        Collections.shuffle(num1List, random); // 随机打乱赛道
        Collections.shuffle(num2List, random); // 随机打乱赛道
        Collections.shuffle(num3List, random); // 随机打乱赛道
        Collections.shuffle(num4List, random); // 随机打乱赛道

        //打乱所有集合的顺序

        //第一次抽签只需要考虑固定的情况 { 1、固定再1赛道的优先处理  2、固定在2赛道的选手需要和1赛道是交叉的  }
         for (TrackDrawDO trackDrawDO : trackDrawDOS) {
            if(null!=trackDrawDO.getPlaceNum() ||  null!=trackDrawDO.getPlaceNum2()){
                //固定在第一天
                if(null!=trackDrawDO.getPlaceNum()){
                    trackDrawDO.setTrack(trackDrawDO.getPlaceNum());
                    numList.remove(trackDrawDO.getPlaceNum());
                }
                //固定在第二天  （1->4  2->3）
                else if (null!=trackDrawDO.getPlaceNum2()) {
                    //固定在1赛道
                    if(num1ListOld.contains(trackDrawDO.getPlaceNum2())){
                        num4List = getNewList(numList,num4List);
                        numList.remove(num4List.getFirst());
                        trackDrawDO.setTrack(num4List.getFirst());
                        num4List.removeFirst();
                    } else if (num2ListOld.contains(trackDrawDO.getPlaceNum2())) {
                        num3List = getNewList(numList,num3List);
                        numList.remove(num3List.getFirst());
                        trackDrawDO.setTrack(num3List.getFirst());
                        num3List.removeFirst();
                    } else if (num3ListOld.contains(trackDrawDO.getPlaceNum2())) {
                        num2List = getNewList(numList,num2List);
                        numList.remove(num2List.getFirst());
                        trackDrawDO.setTrack(num2List.getFirst());
                        num2List.removeFirst();
                    } else {
                        num1List = getNewList(numList,num1List);
                        numList.remove(num1List.getFirst());
                        trackDrawDO.setTrack(num1List.getFirst());
                        num1List.removeFirst();
                    }
                }
            }
            //未固定的情况
            else {
                trackDrawDO.setTrack(numList.getFirst());
                numList.removeFirst();
            }
        }

        this.updateBatchById(trackDrawDOS);


        return Result.ok(trackDrawDOS);
    }

    public LinkedList<String> getNewList(LinkedList<String> numList,LinkedList<String> numNewList){
        while (true){
            if(numList.contains(numNewList.getFirst())){
                break;
            }
            numNewList.removeFirst();
        }

        return numNewList;
    }

    //第二次抽签
    public Result<List<TrackDrawDO>> trackDrawC(List<TrackDrawDO> trackDrawDOS){
        LinkedList<String> numList = new LinkedList<>();//存储所有数据
        LinkedList<String> num1List = new LinkedList<>();//存储上午场1赛道数据
        LinkedList<String> num2List = new LinkedList<>();//存储上午场2赛道数据
        LinkedList<String> num3List = new LinkedList<>();//存储下午场1赛道数据
        LinkedList<String> num4List = new LinkedList<>();//存储下午场2赛道数据
        LinkedList<String> num1ListOld = new LinkedList<>();
        LinkedList<String> num2ListOld = new LinkedList<>();
        LinkedList<String> num3ListOld = new LinkedList<>();
        LinkedList<String> num4ListOld = new LinkedList<>();
        //这里写死64组学校，不考虑缺赛选手
        for (int i = 1; i <= 64; i++) {
            if(i<=16){
                num1List.add(String.valueOf(i));
                num1ListOld.add(String.valueOf(i));
            } else if (i<=32) {
                num2List.add(String.valueOf(i));
                num2ListOld.add(String.valueOf(i));
            } else if (i<=48) {
                num3List.add(String.valueOf(i));
                num3ListOld.add(String.valueOf(i));
            } else{
                num4List.add(String.valueOf(i));
                num4ListOld.add(String.valueOf(i));
            }
            numList.add(String.valueOf(i));
        }
        Random random = new Random();
        Collections.shuffle(numList, random);  // 随机打乱赛道
        Collections.shuffle(num1List, random); // 随机打乱赛道
        Collections.shuffle(num2List, random); // 随机打乱赛道
        Collections.shuffle(num3List, random); // 随机打乱赛道
        Collections.shuffle(num4List, random); // 随机打乱赛道

        for (TrackDrawDO trackDrawDO : trackDrawDOS) {
            //只需要考虑固定在2的
            if(null!=trackDrawDO.getPlaceNum2()){
                trackDrawDO.setTrack2(trackDrawDO.getPlaceNum2());
                numList.remove(trackDrawDO.getPlaceNum2());
            }else {
                if(num1ListOld.contains(trackDrawDO.getTrack())){
                    num4List = getNewList(numList,num4List);
                    numList.remove(num4List.getFirst());
                    trackDrawDO.setTrack2(num4List.getFirst());
                    num4List.removeFirst();
                } else if (num2ListOld.contains(trackDrawDO.getTrack())) {
                    num3List = getNewList(numList,num3List);
                    numList.remove(num3List.getFirst());
                    trackDrawDO.setTrack2(num3List.getFirst());
                    num3List.removeFirst();
                } else if (num3ListOld.contains(trackDrawDO.getTrack())) {
                    num2List = getNewList(numList,num2List);
                    numList.remove(num2List.getFirst());
                    trackDrawDO.setTrack2(num2List.getFirst());
                    num2List.removeFirst();
                } else {
                    num1List = getNewList(numList,num1List);
                    numList.remove(num1List.getFirst());
                    trackDrawDO.setTrack2(num1List.getFirst());
                    num1List.removeFirst();
                }
            }
        }


        this.updateBatchById(trackDrawDOS);


        return Result.ok(trackDrawDOS);
    }

    /**
     * 查询上一次抽签接口
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<TrackDrawDO> trackList(TrackDrawDO trackDrawDTO) {
        //存储抽签你信息
        TrackDrawDO resultVO = new TrackDrawDO();

        boolean hasDraw = true;//默认为true.不存在上次抽签结果时改为false

        //查询上一次的抽签结果
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = new ArrayList<>();
         trackDrawDOS = this.selectList(wrapper);
        //如果没有抽签上一次抽签结果那就默认初始化
        if(trackDrawDOS==null || trackDrawDOS.size()==0){
            hasDraw = false;
            Wrapper<StuSignUpComDO> entityWrapper =new EntityWrapper<>();
            List<StuSignUpComDO> stuSignUpComDOS = stuSignUpComService.selectList(entityWrapper);
            List<StuSignUpComDO> distinctStuSignUpComDOS = stuSignUpComDOS.stream()
                    .collect(Collectors.toMap(
                            StuSignUpComDO::getUnitName, // 作为key
                            s -> s, // 作为value
                            (s1, s2) -> {
                                // 合并name，如果s2存在且s1和s2的name不同
                                if (s2 != null) {
                                    s1.setName(s1.getName() + "、" + s2.getName());
                                }

                                return s1;
                            }
                    ))
                    .values() // 获取map中的values
                    .stream() // 再次转化为stream
                    .sorted(Comparator.comparing(StuSignUpComDO::getPlaceNum, Comparator.nullsLast(Comparator.naturalOrder()))
                            .thenComparing(StuSignUpComDO::getPlaceNum2, Comparator.nullsLast(Comparator.naturalOrder())))
                    .collect(Collectors.toList()); // 收集到list
            int i=0;
            for (StuSignUpComDO stuSignUpComDO : distinctStuSignUpComDOS) {
                TrackDrawDO trackDrawDO = new TrackDrawDO();
                BeanUtils.copyProperties(stuSignUpComDO,trackDrawDO);
                trackDrawDO.setSort(i+=1);
                trackDrawDOS.add(trackDrawDO);
            }
            this.insertBatch(trackDrawDOS);
        }
        resultVO.setHasDraw(hasDraw);
        resultVO.setTrackDrawDOList(trackDrawDOS);

        return Result.ok(resultVO);
    }

    /**
     * 选手检录号抽签
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<List<TrackDrawDO>> trackDrawStuList(TrackDrawDO trackDrawDTO) {
        Random random = new Random();
        LinkedList<String> numList = new LinkedList<>();
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);
        for (int i = 1; i <= trackDrawDOS.size(); i++) {
            numList.add(String.valueOf(i));
        }
        Collections.shuffle(numList,random);
        for (TrackDrawDO trackDrawDO : trackDrawDOS) {
            trackDrawDO.setPlaceNum(numList.getFirst());
            numList.removeFirst();
        }
        this.updateBatchById(trackDrawDOS);

        return Result.ok(trackDrawDOS);
    }

    /**
     * 查询选手检录号 上次抽签结果
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<TrackDrawDO> trackStuList(TrackDrawDO trackDrawDTO) {
        //存储抽签你信息
        TrackDrawDO resultVO = new TrackDrawDO();

        boolean hasDraw = true;//默认为true.不存在上次抽签结果时改为false

        //查询上一次的抽签结果
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = new ArrayList<>();
        trackDrawDOS = this.selectList(wrapper);
        //如果没有抽签上一次抽签结果那就默认初始化
        if(trackDrawDOS==null || trackDrawDOS.size()==0){
            hasDraw = false;
            Wrapper<StuSignUpComDO> entityWrapper =new EntityWrapper<>();
            List<StuSignUpComDO> stuSignUpComDOS = stuSignUpComService.selectList(entityWrapper);
            List<StuSignUpComDO> sortedList = stuSignUpComDOS.stream()
                    .collect(Collectors.groupingBy(StuSignUpComDO::getUnitName)) // 分组
                    .entrySet().stream()
                    .flatMap(entry -> entry.getValue().stream()) // 扁平化
                    .sorted(Comparator.comparing(StuSignUpComDO::getUnitName)) // 排序
                    .collect(Collectors.toList()); // 收集到List中
            int i=0;
            for (StuSignUpComDO stuSignUpComDO : sortedList) {
                TrackDrawDO trackDrawDO = new TrackDrawDO();
                BeanUtils.copyProperties(stuSignUpComDO,trackDrawDO);
                trackDrawDO.setSort(i+=1);
                trackDrawDOS.add(trackDrawDO);
            }
            this.insertBatch(trackDrawDOS);
        }
        resultVO.setHasDraw(hasDraw);
        resultVO.setTrackDrawDOList(trackDrawDOS);

        return Result.ok(resultVO);
    }

    /**
     * 模块A制定照护计划检录号抽签
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<List<TrackDrawDO>> trackDrawSchList(TrackDrawDO trackDrawDTO) {
        Random random = new Random();
        LinkedList<String> numList = new LinkedList<>();
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = this.selectList(wrapper);
        for (int i = 1; i <= trackDrawDOS.size(); i++) {
            numList.add(String.valueOf(i));
        }
        Collections.shuffle(numList,random);
        for (TrackDrawDO trackDrawDO : trackDrawDOS) {
            if(null!=trackDrawDO.getPlaceNum()){
                trackDrawDO.setTrack(trackDrawDO.getPlaceNum());
                numList.remove(trackDrawDO.getPlaceNum());
            }else{
                trackDrawDO.setTrack(numList.getFirst());
                numList.removeFirst();
            }
        }
        this.updateBatchById(trackDrawDOS);

        return Result.ok(trackDrawDOS);
    }

    /**
     * 模块A制定照护计划检录号抽签 查询上一次抽签接口
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<TrackDrawDO> trackSchList(TrackDrawDO trackDrawDTO) {
        //存储抽签你信息
        TrackDrawDO resultVO = new TrackDrawDO();

        boolean hasDraw = true;//默认为true.不存在上次抽签结果时改为false

        //查询上一次的抽签结果
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.orderBy(true,"sort");
        List<TrackDrawDO> trackDrawDOS = new ArrayList<>();
        trackDrawDOS = this.selectList(wrapper);
        //如果没有抽签上一次抽签结果那就默认初始化
        if(trackDrawDOS==null || trackDrawDOS.size()==0){
            hasDraw = false;
            Wrapper<StuSignUpComDO> entityWrapper =new EntityWrapper<>();
            List<StuSignUpComDO> stuSignUpComDOS = stuSignUpComService.selectList(entityWrapper);
            List<StuSignUpComDO> distinctStuSignUpComDOS = stuSignUpComDOS.stream()
                    .collect(Collectors.toMap(StuSignUpComDO::getUnitName, s -> s, (s1, s2) -> {
                        // 如果placeNum不为空，优先保留具有非空placeNum的对象
                        if (s1.getPlaceNum() != null && !s1.getPlaceNum().isEmpty()) {
                            return s1;
                        } else {
                            return s2;
                        }
                    }))
                    .values()
                    .stream()
                    .sorted(Comparator.comparing(StuSignUpComDO::getPlaceNum, Comparator.nullsLast(Comparator.naturalOrder())))
                    .collect(Collectors.toList());
            int i=0;
            for (StuSignUpComDO stuSignUpComDO : distinctStuSignUpComDOS) {
                TrackDrawDO trackDrawDO = new TrackDrawDO();
                BeanUtils.copyProperties(stuSignUpComDO,trackDrawDO);
                trackDrawDO.setSort(i+=1);
                trackDrawDOS.add(trackDrawDO);
            }
            this.insertBatch(trackDrawDOS);
        }
        resultVO.setHasDraw(hasDraw);
        resultVO.setTrackDrawDOList(trackDrawDOS);

        return Result.ok(resultVO);
    }
}


